组合优于继承,多用组合,少用继承
继承
面向对象四个特性之一,用来表示is-a的关系,解决代码复用的问题
不足
- 继承层次过深,过复杂。
- 不利于后期需求的变更,影响代码的可扩展性。
- 代码的可读性变差,需要弄清楚某个类需要哪些方法,必须阅读所有父类的代码。
- 破坏了类的封装性,将父类的实现细节暴露给子类,子类的实现依赖父类的子线,子类和父类高度耦合,一旦父类变化就会影响子类。
案例
鸟的继承体系
- 有会飞的鸟也有不会飞的鸟,,当父类定义一个fly()的方法,则子类都会拥有飞行的功能,对于鸵鸟,可以重写fly()方法,抛出异常即可,这样虽然可行,但是不够优美,违反最少知识原则,暴露了不该暴露的接口给外部。
- 后序考虑鸟会不会叫、鸟下不下单等属性,那么继承体系就非常庞大了。
组合
有什么手段可以代替继承,并且避免继承的不足–组合+接口+委托
多态(接口),运用接口可以实现继承体系中的多态的作用。接口表示某种行为特征,Flyable(可以飞的行为),EggLayable(可下蛋的行为)
代码复用(组合+委托),由于每一个会飞的鸟都要去实现Flyable,所有我们可以定义一个实现类,然后通过组合和委托的形式,将Flyable的实现类组合进去
1 | public interface Flyable{ |
如何决定选择组合还是继承
组合的不足
- 更细粒度的类划分,更多的类和接口
- 增加代码的复杂程度和维护成本
继承的不足
- 继承层次过深灰降低代码的扩展性
- 代码可读性差
继承的条件
- 类之间的继承结构稳定(不会轻易改变)
- 继承层次浅(2-3层)
- 继承关系简单
继承和组合在设计模式中的应用
- 继承(模板模式)
- 组合(装饰器模式、策略模式、组合模式)
多用组合,少用继承并不是绝对的,需要具体情况具体分析,控制好他们的副作用,发挥他们各自的优势。